﻿using GylCSharpUtils.Common.DataStruct;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GylCSharpUtils.GSerializer.Utils {
    public class CirularRefTable {
        private Drawer<Type, object> objs = new Drawer<Type, object>();
        private Drawer<Type, SerialObjID> sers = new Drawer<Type, SerialObjID>();
        /// <summary>
        /// 存放id对应的index
        /// </summary>
        private Dictionary<SerialObjID, int> indexs = new Dictionary<SerialObjID, int>();
        private Dictionary<SerialObjID, Type> types = new Dictionary<SerialObjID, Type>();

        public CirularRefTable() { }

        public int AddCirularRefObj(SerialObjID sId, object obj) {
            CheckNull(sId, obj);
            Type t = obj.GetType();
            var i1 = objs.Add(t, obj);
            var i2 = sers.Add(t,sId);
            if(i1 != i2) throw new Exception("发生异常，添加后的索引不相等");
            indexs.Add(sId, i1);
            types.Add(sId, t);
            return i1;
        }

        /// <summary>
        /// 检查是否有循环引用，若有直接返回第一次的ID，若无则返回null
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public SerialObjID CheckObj(object obj) {
            if(obj == null) return null;
            Type t = obj.GetType();
            var l = objs.Values(t);
            for(int i=0; i< l.Count; i++) {
                if(obj == l[i]) {
                    return sers.Value(t, i);
                }
            }
            return null;
            
        }

        public object GetObj(SerialObjID sId) {
            if(!indexs.ContainsKey(sId)) return null;
            return objs.Value(types[sId], indexs[sId]);
        }

        public void CheckNull(params object[] objs) {
            if(objs == null || objs.Length == 0) return;
            foreach(var obj in objs) {
                if(obj == null) throw new Exception("不可添加空对象");
            }
            
        }
    }
}
